package frameWork.mainComponent;

import frameWork.entity.NodeDrawBase;
import frameWork.util.Vector2D;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class MainDrawer extends JComponent {
    private static MainDrawer myDramwe;
    public static MainDrawer getMainDrawer(){
        return myDramwe;
    }

    public MainDrawer() throws Exception {
        addListener();
        if (myDramwe != null)
            throw new Exception("不允许多开画板");
        myDramwe = this;
    }

    BufferedImage bufTemp = new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);//缓存机制
    BufferedImage bufBack = null;//new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);
    BufferedImage bufMain = new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);
    BufferedImage bufOper = new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);

    private BlockingDeque<NodeDrawBase> blockingDeque =new LinkedBlockingDeque<>();

    /**
     *  主要调用的画图(相当于游戏画面线程）
     */
    public boolean mainPaint(){
        if (!drawable)
            return drawable;
        drawable = false;
        if(bufBack==null){
            bufBack=new BufferedImage(2920, 2080,BufferedImage.TYPE_INT_ARGB);
            paintBackground();
        }
        bufMain =new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);
        paintMain();

        BufferedImage temp=new BufferedImage(1920, 1080,BufferedImage.TYPE_INT_ARGB);
        ((Graphics2D)temp.getGraphics()).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        temp.getGraphics().drawImage(bufBack, (int)(nowDrag.getX())%10-10, (int)(nowDrag.getY())%10-10, bufBack.getWidth(), bufBack.getHeight(),null);
        temp.getGraphics().drawImage(bufMain, 0, 0, bufMain.getWidth(), bufMain.getHeight(),null);
        bufTemp=temp;
        drawable = true;
        //repaint();
        return drawable;
    }

    private boolean drawable=true;


    //Point startDrag, endDrag;
    Point2D startDrag;
    Point2D nowDrag=new Point2D.Double(0,0);

    public void addListener() {
        this.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                startDrag = new Point(e.getX(), e.getY());
                //detDrag = new Point(0, 0);
                //endDrag = startDrag;
            }
            public void mouseReleased(MouseEvent e) {
//                if (endDrag != null)
//                    detDrag = new Point(e.getX() - endDrag.x, e.getY() - endDrag.y);
//                else
//                    detDrag = new Point(0, 0);
                startDrag = null;
                //endDrag = null;
            }
        });
        this.addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent e) {
//                if (endDrag != null)
//                    detDrag = new Point(e.getX() - endDrag.x, e.getY() - endDrag.y);
//                else
//                    detDrag = new Point(0, 0);
//                endDrag = new Point(e.getX(), e.getY());
                if(startDrag!=null)nowDrag= Vector2D.jia(nowDrag,new Point2D.Double(e.getX()-startDrag.getX(),e.getY()-startDrag.getY()));
                startDrag=new Point2D.Double(e.getX(),e.getY());
            }
        });
    }


    public void add(NodeDrawBase node){
        try {
            blockingDeque.put(node);
        }catch (InterruptedException e){
            //
        }
    }


    @Override
    public void paint(Graphics gs) {
        Graphics2D g = (Graphics2D) gs;
//        g.setPaint(new Color(0xff,0xff,0xff,0xff));
//        g.fillRect(0, 0, this.getWidth(), this.getHeight());

        if (!drawable) {
            g.drawImage(bufTemp, 0, 0, bufTemp.getWidth(), bufTemp.getHeight(), null);
            return;
        }
        //g.drawImage(bufBack, 0, 0, bufBack.getWidth(), bufBack.getHeight(),null);
        //g.drawImage(bufMain, 0, 0, bufMain.getWidth(), bufMain.getHeight(),null);

        g.drawImage(bufTemp, 0, 0, bufTemp.getWidth(), bufTemp.getHeight(),null);

//        if ((touchType & 8) != 0)// middle
//            paintMove(g);
//        if ((touchType & 16) != 0)// right
//            paintOperator(g);
//        if ((touchType & 4) != 0)// middle
//            paintLink(g);


        //drawable=true;
    }

    private void paintMain() {
        bufMain = resize(bufMain);
        Graphics2D g = (Graphics2D) bufMain.getGraphics();
        g.setStroke(new BasicStroke(1));
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.50f));
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        try {
            while(!blockingDeque.isEmpty()){
                NodeDrawBase node= blockingDeque.take();
                node.paint(g,nowDrag);
            }
        }catch (InterruptedException e){
            //
        }
        // System.out.println("s");
        //for (Node n : nodes) {
//        for(int i=0;i<nodes.size();i++){
//            nodes.get(i).painting(g);
//        }
//        if (nodes.size() != 0)
//            nodesBack = nodes;
//        nodes = new Vector<Node>();
        g.dispose();
    }

    private BufferedImage resize(BufferedImage buf) {
        if (buf.getWidth() < this.getWidth() || buf.getHeight() < this.getHeight()) {
            BufferedImage tmp = new BufferedImage(this.getWidth(),
                    this.getHeight(), BufferedImage.TYPE_INT_ARGB);
            tmp.getGraphics().drawImage(buf, 0, 0, buf.getWidth(),
                    buf.getHeight(), null);
            return tmp;
        }
        return buf;
    }

    private void paintBackground() {
        bufBack = resize(bufBack);
        Graphics2D g = (Graphics2D) bufBack.getGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setPaint(Color.LIGHT_GRAY);
        for (int i = 0; i < bufBack.getWidth(); i += 10) {
            Shape line = new Line2D.Float(i, 0, i, bufBack.getHeight());
            g.draw(line);
        }
        for (int i = 0; i < bufBack.getHeight(); i += 10) {
            Shape line = new Line2D.Float(0, i, bufBack.getWidth(), i);
            g.draw(line);
        }
        // bufBack =ChangeImage.rotateImage(bufBack,60);
        g.dispose();
    }

}
